package de.connecttext.services;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

import de.connecttext.model.MetaData;

/**
 * Class to extract MetaData from a given Text. The Type of input and its form
 * should be specified by the respective methods (e.g. xml format etc.)
 * 
 * @author conrad
 * 
 */
public class MetaDataExtractor {

	/**
	 * Expects to be fed with a String "snippet" that has the desired data right
	 * behind an </em> Tag, as when solr highlights "<em>Title</em>: Blue
	 * Mountain". returns "Blue Mountain"
	 * 
	 * @param snippet
	 * @return
	 */
	public String extractMetaDataFragmentFromGutenBergSnippet(String snippet) {

		int lastIndexOfArrayBracket = snippet.lastIndexOf("em>");
		snippet = snippet.substring(lastIndexOfArrayBracket + 3);
		String[] split = snippet.split("\\n");
		if (split[0] != null) {
			snippet = split[0].trim();
			Pattern p0 = Pattern.compile(":(.+)");
			Matcher m0 = p0.matcher(snippet);
			if (m0.matches()) {
				snippet = m0.group(1).trim();
			}
			return snippet;
		} else
			return null;

	}

	public MetaData extractMetaDataFromProjectGutenbergString(
			String extractMetaDataFrom) {
		MetaData metaData = new MetaData();

		String authorCandidate = null;
		String titleCandidate = null;
		metaData.setAuthor(authorCandidate);
		metaData.setTitle(titleCandidate);

		/**
		 * String of the form "<em>Project</em> <em>Gutenberg</em>
		 * <em>Etext</em> Story of My Heart, by Richard Jefferies" is expected,
		 * if it differs broadly, the extraction fails
		 */

		String[] split = extractMetaDataFrom.split("\\n");
		// Der String muss getrimmt werden, um überschüssige Steuerzeichen zu
		// entfernen.
		String firstLine = "";
		String secondLine = "";
		if (split[0] != null)
			firstLine = split[0].trim();
		if (split[1] != null)
			secondLine = split[1].trim();

		// Zuerst wird der Teil mit den Tags abgeschnitten
		int lastIndexOfArrayBracket = firstLine.lastIndexOf(">");
		int lastIndexOfGutenberg = firstLine.lastIndexOf("Gutenberg");
		if (lastIndexOfArrayBracket != -1) {
			firstLine = firstLine.substring(lastIndexOfArrayBracket + 1);
		} else if (lastIndexOfGutenberg != -1) {
			firstLine = firstLine.substring(lastIndexOfGutenberg + 1);
		} else {
			System.out
					.println("Anfangsbedingungen beim Parsen nicht erfüllt: Weder <em> Tags noch 'Gutenberg' enthalten");
			return metaData;
		}
		// System.out.println(firstLine + secondLine);

		// Patterns to strip Etext, Ebook or "'s"
		Pattern stripP0 = Pattern
				.compile("(.*)(Etext|EText|Ebook|EBook|eBook|'s)(.+)");
		Matcher stripM0 = stripP0.matcher(firstLine);
		if (stripM0.matches()) {
			firstLine = stripM0.group(stripM0.groupCount());
		}
		Pattern stripP1 = Pattern.compile("(.*)(of)(.+)");
		Matcher stripM1 = stripP1.matcher(firstLine);
		if (stripM1.matches()) {
			firstLine = stripM1.group(stripM1.groupCount());
		}

		Pattern p0 = Pattern.compile(",?(.+)(,|by).+by(.*)");
		Matcher m0 = p0.matcher(firstLine);

		Pattern p1 = Pattern.compile("(.+)by(.+)");
		Matcher m1 = p1.matcher(firstLine);

		Pattern p2 = Pattern.compile("(.*)by(.+)");
		Matcher m2 = p2.matcher(secondLine);

		// Wenn Titel und Autor nach dem obigen Muster enthalten sind, sollte m0
		// bereits matchen
		if (m0.matches()) {
			if (m0.groupCount() > 0)
				titleCandidate = m0.group(1);
			if (m0.groupCount() > 2)
				authorCandidate = m0.group(3);

		} else if (m1.matches()) {
			// Wenn nicht, dann vielleicht nur mit by, ohne Komma

			titleCandidate = m1.group(1);
			authorCandidate = m1.group(2);

		} else if (m2.matches()) {
			titleCandidate = firstLine;
			authorCandidate = m2.group(m2.groupCount());

		} else if (firstLine.length() > 4 && secondLine.length() > 4) {
			titleCandidate = firstLine;
			authorCandidate = secondLine;

		} else {
			// Wenn alle Stricke reißen, sei der Titel die erste Zeile, autor
			// unbekannt!
			titleCandidate = firstLine;

		}

		if (authorCandidate == null)
			metaData.setAuthor(authorCandidate);
		else
			metaData.setAuthor(authorCandidate.trim());
		if (titleCandidate == null)
			metaData.setTitle(titleCandidate);
		else
			metaData.setTitle(titleCandidate.trim());
		return metaData;
	}
}
